﻿using Culvert_Help;
using NeXus.BIMBase;
using NeXus.BIMBase.Core;
using NeXus.BIMBase.Data;
using NeXus.BIMBase.SolidCore;
using NeXus.p3d;
using System;
using System.Collections.Generic;
using static NeXus.p3d.GeCurveArray;

namespace checc_baseTools
{
    public class TaperedSlope
    {
        public static List<BPGraphics> bPGraphics1 = new List<BPGraphics>();
        //锥坡最高截面高度
        public static double Height;
        //锥坡半径
        public static double Radius;
        //锥坡角度
        public static double Angle = 90;

        /// <summary>
        /// 锥坡
        /// </summary>
        /// <param name="slope">断面坡比</param>
        /// <param name="innerEdge">内襟边</param>
        /// <param name="distance_W">净跨</param>
        /// <param name="distance_H">净高</param>
        /// <param name="coverThickness">盖板厚度</param>
        /// <param name="thickness_pave">铺砌厚度</param>
        /// <param name="baseDepth">基础深度</param>
        /// <param name="baseEdgeWidth">基础襟边宽度</param>
        public static Tuple<BPGraphicsCollection, GePoint3dCollection> drawConeSlope(double slope, double innerEdge, double distance_W, double distance_H, double coverThickness, double thickness_pave, double paveSlope, double baseDepth, double baseEdgeWidth, double angle)
        {
            //左洞口
            GePoint3d bottomCenter_L = GePoint3d.createByZero();
            GePoint3d topCenter = GePoint3d.createByZero();
            if (paveSlope > 0)
            {
                //八字墙最高截面高度S
                Height = distance_H + coverThickness + thickness_pave;
                //半径为带铺砌厚度的半径
                Radius = Height * slope;
                //圆锥底圆心
                //计算原点的y值是计算不加铺砌厚度的的y值 才可以裁完在洞口处
                //这里的半径是不带铺砌厚度的
                bottomCenter_L = new GePoint3d(0, -distance_W / 2 - innerEdge - ((distance_H + coverThickness) * slope), -thickness_pave);
                topCenter = new GePoint3d(bottomCenter_L.x, bottomCenter_L.y, Height - thickness_pave);
            }
            else
            {
                //八字墙最高截面高度S
                Height = distance_H + coverThickness;
                Radius = slope * Height;
                //圆锥底圆心
                bottomCenter_L = new GePoint3d(0, -distance_W / 2 - innerEdge - Radius, 0);
                topCenter = new GePoint3d(bottomCenter_L.x, bottomCenter_L.y, Height);
            }

            //创建圆锥
            GeConeInfo coneInfo = new GeConeInfo(bottomCenter_L, topCenter, Radius, 0, true);
            IGeSolidBase cone = Element_solid.getCreateConeSlope(coneInfo);
            //合集拉伸体 三菱柱
            GePoint3dCollection points = new GePoint3dCollection
            {
                bottomCenter_L,
                new GePoint3d(bottomCenter_L.x + Radius * 5, bottomCenter_L.y, bottomCenter_L.z),
                new GePoint3d(bottomCenter_L.x, bottomCenter_L.y + Radius * 5, bottomCenter_L.z)
            };

            GeCurveArray curveList = GeCurveArray.createLinestringArray(points, BoundaryType.BOUNDARY_TYPE_Outer, true);

            GeExtrusionInfo extrusionInfo = new GeExtrusionInfo(curveList, new GeVec3d(0, 0, Height * 2), true);
            IGeSolidBase soild = Element_solid.getTensileBody(extrusionInfo);
            BPGraphics coneSlope_L = Element_solid.BoolIntersections(cone, soild, false);


            //左侧锥坡基础
            //左侧顶底圆心
            GePoint3d foundationTC = new GePoint3d(bottomCenter_L.x, bottomCenter_L.y - baseEdgeWidth, 0);
            GePoint3d foundationBC_L = new GePoint3d(bottomCenter_L.x, bottomCenter_L.y - baseEdgeWidth, -baseDepth);
            //圆柱
            IGeSolidBase foundation = IGeSolidBase.createGeCone(new GeConeInfo(foundationBC_L, foundationTC, Radius + baseEdgeWidth, Radius + baseEdgeWidth, true));

            //合集拉伸体 三棱柱
            points = new GePoint3dCollection
            {
                foundationBC_L,
                new GePoint3d(foundationBC_L.x + Radius * 5, foundationBC_L.y, foundationBC_L.z),
                new GePoint3d(foundationBC_L.x, foundationBC_L.y + Radius * 5, foundationBC_L.z)
            };

            IGeSolidBase foundationSolid = IGeSolidBase.createGeExtrusion(new GeExtrusionInfo(GeCurveArray.createLinestringArray(points, BoundaryType.BOUNDARY_TYPE_Outer, true), new GeVec3d(0, 0, Height * 2), true));

            BPGraphics foundation_L = Element_solid.BoolIntersections(foundation, foundationSolid, false);


            //右洞口
            GePoint3d bottomCenter_R = GePoint3d.createByZero();
            if (paveSlope > 0)
            {
                //八字墙最高截面高度S
                Height = distance_H + coverThickness + thickness_pave;
                //半径为带铺砌厚度的半径
                Radius = Height * slope;
                //圆锥底圆心
                //计算原点的y值是计算不加铺砌厚度的的y值 才可以裁完在洞口处
                //这里的半径是不带铺砌厚度的
                bottomCenter_R = new GePoint3d(0, distance_W / 2 + innerEdge + ((distance_H + coverThickness) * slope), -thickness_pave);
                topCenter = new GePoint3d(bottomCenter_R.x, bottomCenter_R.y, Height - thickness_pave);
            }
            else
            {
                //八字墙最高截面高度S
                Height = distance_H + coverThickness;
                Radius = slope * Height;
                //圆锥底圆心
                bottomCenter_R = new GePoint3d(0, distance_W / 2 + innerEdge + Radius, 0);
                topCenter = new GePoint3d(bottomCenter_R.x, bottomCenter_R.y, Height);
            }
            //创建圆锥
            coneInfo = new GeConeInfo(bottomCenter_R, topCenter, Radius, 0, true);
            cone = Element_solid.getCreateConeSlope(coneInfo);

            //拉伸体 三菱柱
            points = new GePoint3dCollection
            {
                bottomCenter_R,
                new GePoint3d(bottomCenter_R.x + Radius * 5, bottomCenter_R.y, bottomCenter_R.z),
                new GePoint3d(bottomCenter_R.x, bottomCenter_R.y - Radius * 5, bottomCenter_R.z)
            };

            soild = IGeSolidBase.createGeExtrusion(new GeExtrusionInfo(GeCurveArray.createLinestringArray(points, BoundaryType.BOUNDARY_TYPE_Outer, true), new GeVec3d(0, 0, Height * 2), true));

            BPGraphics coneSlope_R = Element_solid.BoolIntersections(cone, soild, false);

            //右侧锥坡基础
            //右侧圆心－基础襟边宽度,半径＋基础襟边宽度
            GePoint3d foundationTC_R = new GePoint3d(bottomCenter_R.x, bottomCenter_R.y + baseEdgeWidth, 0);
            GePoint3d foundationBC_R = new GePoint3d(bottomCenter_R.x, bottomCenter_R.y + baseEdgeWidth, -baseDepth);
            GeConeInfo coneInfo2 = new GeConeInfo(foundationBC_R, foundationTC_R, Radius + baseEdgeWidth, Radius + baseEdgeWidth, true);
            foundation = Element_solid.getCreateConeSlope(coneInfo2);

            //拉伸体 三菱柱
            points = new GePoint3dCollection
            {
                foundationBC_R,
                new GePoint3d(foundationBC_R.x + Radius * 5, foundationBC_R.y, foundationBC_R.z),
                new GePoint3d(foundationBC_R.x, foundationBC_R.y - Radius * 5, foundationBC_R.z)
            };

            IGeSolidBase foundationSoild_R = IGeSolidBase.createGeExtrusion(new GeExtrusionInfo(GeCurveArray.createLinestringArray(points, BoundaryType.BOUNDARY_TYPE_Outer, true), new GeVec3d(0, 0, Height * 2), true));

            BPGraphics foundation_R = Element_solid.BoolIntersections(foundation, foundationSoild_R, false);

            //左右锥坡
            BPGraphics graphics = Element_solid.BoolCollection(coneSlope_L, coneSlope_R, false);
            //graphics = Helper.unitRotation(graphics, angle);
            //左右基础
            BPGraphics graphics1 = Element_solid.BoolCollection(foundation_L, foundation_R, false);

            graphics1 = Helper.unitRotation(graphics1, angle);
            bottomCenter_L.set(bottomCenter_L.x, bottomCenter_L.y, 0);
            bottomCenter_R.set(bottomCenter_R.x, bottomCenter_R.y, 0);
            GePoint3dCollection point3Ds = new GePoint3dCollection()
            {
                bottomCenter_L,
                bottomCenter_R
            };
            return new Tuple<BPGraphicsCollection, GePoint3dCollection>(new BPGraphicsCollection { graphics, graphics1 }, point3Ds);
        }


        /// <summary>
        /// 铺砌，截水墙
        /// </summary>
        /// <param name="bottomCenter">左洞口底部圆心</param>
        /// <param name="paveOffset">铺砌外延</param>
        /// <param name="paveSlope">铺砌坡度</param>
        /// <param name="CutoffWall_H">截水墙高度</param>
        /// <param name="thickness_pave">铺砌厚度</param>
        /// <param name="CutoffWall_W">截水墙厚度</param>
        public static Tuple<BPGraphics, Dictionary<string, double>, GePoint3dCollection> PaveAndCutoffWall(GePoint3dCollection bottomCenter, double paveOffset, double paveSlope, double CutoffWall_H, double thickness_pave, double CutoffWall_W, double baseEdgeWidth)
        {
            BPProject project = BPApplication.getInstance().getProjectManager().getMainProject();
            BPModelBase model = project.getActiveModel();
            //左侧近洞口的点
            GePoint3d Left = new GePoint3d(bottomCenter[0].x, bottomCenter[0].y - baseEdgeWidth, bottomCenter[0].z);
            //左侧远洞口的点
            GePoint3d Left1 = new GePoint3d(Left.x + Radius + paveOffset + baseEdgeWidth, Left.y, Left.z);
            //右侧近洞口的点
            GePoint3d Right = new GePoint3d(bottomCenter[1].x, bottomCenter[1].y + baseEdgeWidth, bottomCenter[1].z);
            //左侧远洞口的点
            GePoint3d Right1 = new GePoint3d(Right.x + Radius + paveOffset + baseEdgeWidth, Right.y, Right.z); ;
            //铺砌底面点集
            GePoint3dCollection ptBot = new GePoint3dCollection()
            {
                Left,Left1,Right1,Right
            };
            //铺砌底面
            GeCurveArray curveArray = GeCurveArray.createLinestringArray(ptBot, BoundaryType.BOUNDARY_TYPE_Outer, true);
            double angle = Math.Atan(paveSlope) * 180 / Math.PI;
            //坡度，矩阵变化
            GeRotMatrix rotMatrix = GeRotMatrix.createByVectorAndRotationAngle(new GeVec3d(0, 1, 0), angle * Math.PI / 180);
            GeTransform transform = GeTransform.create(rotMatrix, GePoint3d.createByZero());
            curveArray.setByTransform(transform);
            //拉伸成体
            GeVec3d v3d = new GeVec3d(0, 0, -thickness_pave);
            GeExtrusionInfo extrusionInfo = new GeExtrusionInfo(curveArray, v3d, true);
            IGeSolidBase solid = Element_solid.getTensileBody(extrusionInfo);
            BPGraphics graphic = model.createPhysicalGraphics();
            graphic.addSolid(solid);
            double paveVolume = 0;
            BPSolidCoreUtil.getEntityVolume(ref paveVolume, graphic.getEntityR());


            //截水墙
            //点
            GePoint3d cutoffWall_Left = Left1;
            GePoint3d cutoffWall_Left2 = new GePoint3d(Left1.x - CutoffWall_W, Left1.y, Left1.z);
            GePoint3d cutoffWall_Right = Right1;
            GePoint3d cutoffWall_Right2 = new GePoint3d(Right1.x - CutoffWall_W, Right1.y, Right1.z);
            //截水墙顶面点集
            GePoint3dCollection ptTop = new GePoint3dCollection()
            {
                cutoffWall_Left,cutoffWall_Left2,cutoffWall_Right2,cutoffWall_Right
            };

            //铺砌底面
            GeCurveArray curve = GeCurveArray.createLinestringArray(ptTop, BoundaryType.BOUNDARY_TYPE_Outer, true);
            curve.setByTransform(transform);
            //体
            GeVec3d CutoffWall_v3d = new GeVec3d(0, 0, -CutoffWall_H);
            GeExtrusionInfo extrusionInfo1 = new GeExtrusionInfo(curve, CutoffWall_v3d, true);
            IGeSolidBase CutoffWall = Element_solid.getTensileBody(extrusionInfo1);
            BPGraphics cutoffWallGp = model.createPhysicalGraphics();
            cutoffWallGp.addSolid(CutoffWall);
            //截水墙体积
            double cutoffWallVolume = 0;
            BPSolidCoreUtil.getEntityVolume(ref cutoffWallVolume, cutoffWallGp.getEntityR());
            //截水墙长
            double cutoffWallLength = cutoffWall_Left.distance(cutoffWall_Right);
            //铺砌表面积
            double paveGrassArea = (Radius + paveOffset) * cutoffWallLength - Math.PI * Math.Pow(Radius, 2) / 2;
            //铺砌和截水墙合集
            graphic = Element_solid.BoolCollection(graphic, cutoffWallGp, false);
            Dictionary<string, double> keyValuePairs = new Dictionary<string, double>();
            keyValuePairs.Add("铺砌体积", paveVolume);
            keyValuePairs.Add("铺砌表面积", paveGrassArea);
            keyValuePairs.Add("截水墙体积", cutoffWallVolume);
            keyValuePairs.Add("截水墙墙长", cutoffWallLength);

            //ElementAttribute.SettingMaterial(graphic, material);
            return new Tuple<BPGraphics, Dictionary<string, double>, GePoint3dCollection>(graphic, keyValuePairs, ptBot);
        }


        /// <summary>
        /// 锥坡整体
        /// </summary>
        /// <param name="taperedSlope">锥坡实体</param>
        /// <param name="distance_W">净跨</param>
        /// <param name="distance_H">净高</param>
        /// <param name="coverThickness">盖板厚度</param>
        /// <param name="angle">洞口交角</param>
        /// <returns></returns>
        public static Tuple<BPGraphicsCollection, Dictionary<string, double>> createTaperedSlope(TaperedSlopeData taperedSlope, double distance_W, double distance_H, double coverThickness, double angle)
        {
            double slope = taperedSlope.Slope;//断面坡比
            double innerEdge = taperedSlope.InnerEdge * Culvert_Help.GeneralHelpers.UOR;//内襟边 
            double paveOffset = taperedSlope.PaveOffset * Culvert_Help.GeneralHelpers.UOR;//铺砌外延
            double paveSlope = taperedSlope.PaveSlope * 0.01;//铺砌坡度
            double baseDepth = taperedSlope.BaseDepth * Culvert_Help.GeneralHelpers.UOR;//基础深度
            double baseEdgeWidth = taperedSlope.BaseEdgeWidth * Culvert_Help.GeneralHelpers.UOR;//基础襟边宽度
            double CutoffWall_H = taperedSlope.CutoffWall_H * Culvert_Help.GeneralHelpers.UOR;//截水墙高度
            double thickness_pave = taperedSlope.Thickness_pave * Culvert_Help.GeneralHelpers.UOR;//铺砌厚度
            double CutoffWall_W = taperedSlope.CutoffWall_W * Culvert_Help.GeneralHelpers.UOR;//截水墙厚度
            distance_W = distance_W * Culvert_Help.GeneralHelpers.UOR;//净跨
            distance_H = distance_H * Culvert_Help.GeneralHelpers.UOR;//净高
            coverThickness = coverThickness * Culvert_Help.GeneralHelpers.UOR;//盖板厚度
            distance_W = distance_W / Math.Cos(Math.PI * angle / 180);//有角度的净跨
            //锥坡
            Tuple<BPGraphicsCollection, GePoint3dCollection> coneSlope = drawConeSlope(slope, innerEdge, distance_W, distance_H, coverThickness, thickness_pave, paveSlope, baseDepth, baseEdgeWidth, angle);
            //锥坡体积
            double coneSlopeVolume = 0;
            BPSolidCoreUtil.getEntityVolume(ref coneSlopeVolume, coneSlope.Item1[0].getEntityR());
            //锥坡表面积
            double coneSlopeSurfaceArea = 0;
            BPSolidCoreUtil.getEntityArea(ref coneSlopeSurfaceArea, coneSlope.Item1[0].getEntityR());
            //锥坡植草面积
            double l = Math.Sqrt(Math.Pow(Height, 2) + Math.Pow(Radius, 2));
            double coneSlopegrassArea = Math.PI * l / 2;

            //铺砌截水墙
            Tuple<BPGraphics, Dictionary<string, double>, GePoint3dCollection> PaveAndCutoffWallGp = PaveAndCutoffWall(coneSlope.Item2, paveOffset, paveSlope, CutoffWall_H, thickness_pave, CutoffWall_W, baseEdgeWidth);
            BPGraphics graphic = PaveAndCutoffWallGp.Item1;
            //剪完的锥坡
            BPGraphics bPGraphics = Element_solid.BoolDifferenceSet(coneSlope.Item1[0], PaveAndCutoffWallGp.Item1, false);
            //锥坡基础
            BPGraphics graphics = coneSlope.Item1[1];
            //基础体积
            double baseVolume = 0;
            BPSolidCoreUtil.getEntityVolume(ref baseVolume, coneSlope.Item1[1].getEntityR());
            //旋转洞口角度
            graphic = Helper.unitRotation(graphic, angle);
            bPGraphics = Helper.unitRotation(bPGraphics, angle);
            //坡度，矩阵变化
            GeRotMatrix rotMatrix = GeRotMatrix.createByVectorAndRotationAngle(new GeVec3d(0, 1, 0), Math.Atan(paveSlope) * 180 / Math.PI * Math.PI / 180);
            GeTransform transform = GeTransform.create(rotMatrix, GePoint3d.createByZero());
            BPGraphicsUtils.transformPhysicalGraphics(graphics, transform);

            Dictionary<string, double> keyValuePairs = new Dictionary<string, double>();
            keyValuePairs.Add("体积", coneSlopeVolume);
            keyValuePairs.Add("表面积", coneSlopeSurfaceArea);
            keyValuePairs.Add("植草", coneSlopegrassArea);
            keyValuePairs.Add("基础体积", baseVolume);

            foreach (string key in PaveAndCutoffWallGp.Item2.Keys)
            {
                if (!keyValuePairs.ContainsKey(key))
                    keyValuePairs.Add(key, PaveAndCutoffWallGp.Item2[key]);
            }

            //返回锥坡底面四个点的平面
            GeCurveArray geCurveArray = GeCurveArray.createLinestringArray(PaveAndCutoffWallGp.Item3, BoundaryType.BOUNDARY_TYPE_Outer, true);
            BPGraphics plan = GeneralHelpers.Model2D.createPhysicalGraphics();
            plan.addCurveArray(geCurveArray);
            plan = Helper.unitRotation(plan, angle);
            return new Tuple<BPGraphicsCollection, Dictionary<string, double>>(new BPGraphicsCollection { bPGraphics, graphic, graphics, plan }, keyValuePairs);
        }

        #region MyRegion
        ///// <summary>
        ///// 锥坡
        ///// </summary>
        ///// <param name="quadrant">象限</param>
        ///// <param name="angle">锥坡角度</param>
        ///// <param name="radius">锥坡半径</param>
        ///// <param name="height">锥坡高度</param>
        ///// <param name="color">锥坡颜色</param>
        ///// <param name="materia">锥坡材质</param>
        //public static void drawConeSlope(int quadrant, double angle, double radius, double height, Color color, BPMaterial materia)
        //{
        //    GePoint3d bottomCenter1 = new GePoint3d(0, 0, 0);
        //    GePoint3d topCenter = new GePoint3d(0, 0, height);
        //    GeConeInfo coneInfo = new GeConeInfo(bottomCenter1, topCenter, radius, 0, true);
        //    IGeSolidBase cone = Element_solid.getCreateConeSlope(coneInfo);
        //    double startAngle = 0;
        //    double endAngle = 0;

        //    switch (quadrant)
        //    {
        //        case 1:
        //            startAngle = 0;
        //            endAngle = angle;
        //            break;
        //        case 2:
        //            startAngle = 180;
        //            endAngle = -angle;
        //            break;
        //        case 3:
        //            startAngle = 180;
        //            endAngle = angle;
        //            break;
        //        case 4:
        //            startAngle = 0;
        //            endAngle = -angle;
        //            break;
        //    }


        //    BPModelArc arc = new BPModelArc(new GePoint3d(0, 0, 0), radius + 500, startAngle / 57.2958, endAngle / 57.2958);
        //    var a = GeEllipse3d.createByEllipseCenterStartEnd(new GePoint3d(0, 0, 0), arc.startPoint, arc.endPoint);

        //    GePoint3d pointS = new GePoint3d(0, 0, 0);
        //    GeSegment3d segment = new GeSegment3d(pointS, arc.startPoint);
        //    GeSegment3d segment2 = new GeSegment3d(arc.endPoint, pointS);

        //    var curve = IGeCurveBase.createSegment(segment);
        //    var curve2 = IGeCurveBase.createSegment(segment2);
        //    var curve3 = IGeCurveBase.createEllipse(a);

        //    GeCurveArray curveList = GeCurveArray.create(GeCurveArray.BoundaryType.Outer);
        //    curveList.add(curve);
        //    curveList.add(curve3);
        //    curveList.add(curve2);

        //    GeVec3d v3d = new GeVec3d(0, 0, height);
        //    GeExtrusionInfo extrusionInfo = new GeExtrusionInfo(curveList, v3d, true);
        //    IGeSolidBase soild = Element_solid.getTensileBody(extrusionInfo);
        //    Element_solid.BoolIntersections(cone, soild, color, materia, true);
        //}
        #endregion
    }
}
